feat: store sent notifications to DB - #52
Conversation
…oreNotificationsIntegrationTest
lisajulia
left a comment
There was a problem hiding this comment.
Some small changes, otherwise this is fine :)
Thanks!
|
|
||
| Instant sentAt = Instant.now(); | ||
|
|
||
| for (int i = 0; i < results.size(); i++) { |
There was a problem hiding this comment.
Possibly add a check here that results and entries have the same size.
There was a problem hiding this comment.
Good catch on the size check suggestion! Looking at this more carefully, I realized the loop itself is unnecessary.
In ProductionHandler, each notification is inserted individually in a loop:
for (int i = 0; i < results.size(); i++) {
notificationProviderService.run(Insert.into(Notifications_.CDS_NAME).entry(notification));
}Each run(Insert...) call is a separate OData POST request. Since StoreNotificationsHandler is an @after(EVENT_CREATE) handler on NotificationProviderService, it is triggered after each individual run() call, not once for the entire batch.
I simplified the handler to use results.get(0) and entries.get(0) directly, and removed the loop. The size check is also not needed for the same reason. results.size() will always equal entries.size() (both always 1), since this handler fires per individual insert, not per batch.
| this.storageService = storageService; | ||
| } | ||
|
|
||
| @After(event = "*") |
There was a problem hiding this comment.
This will be after every event, right? Is it possible to narrow that down?
There was a problem hiding this comment.
Narrowing it down would require more complex architectural changes. The filtering already happens at the top of the method with a simple map lookup, which is very cheap. EntityNotificationHandler uses the same pattern.
There was a problem hiding this comment.
Also, it affects local only therefore not that relevant anyway. Tested it out and it worked :)
| priority : String(20); | ||
| navigationTargetObject : String(500); | ||
| navigationTargetAction : String(500); | ||
| sentAt : Timestamp; |
There was a problem hiding this comment.
Mention in the readme that this is UTC time.
| @After(event = CqnService.EVENT_CREATE, entity = Notifications_.CDS_NAME) | ||
| public void storeNotifications(CdsCreateEventContext context) { |
There was a problem hiding this comment.
can be simplified
| @After(event = CqnService.EVENT_CREATE, entity = Notifications_.CDS_NAME) | |
| public void storeNotifications(CdsCreateEventContext context) { | |
| @After | |
| public void storeNotifications(CdsCreateEventContext context, List<CdsData> data) { |
| configurer | ||
| .getCdsRuntime() | ||
| .getEnvironment() | ||
| .getProperty("cds.requires.notifications.storeNotifications", Boolean.class, false); |
There was a problem hiding this comment.
cds.requires is the namespace for require service confiugration -> feature toggles are in cds.
| .getProperty("cds.requires.notifications.storeNotifications", Boolean.class, false); | |
| .getProperty("cds.notifications.storeNotifications", Boolean.class, false); |
| import org.slf4j.LoggerFactory; | ||
|
|
||
| /** Shared service for persisting notifications to the database. */ | ||
| public class NotificationStorageService { |
There was a problem hiding this comment.
This class isn't a service (in cap terms) it is a normal pojo
… instead of cds.requires
…ld is stored in UTC
…dler is triggered per insert
Schmarvinius
left a comment
There was a problem hiding this comment.
think its fine but please await lisas review as well
Summary
Some applications need the notifications stored to DB to do further processing with them. This PR adds optional DB storage for sent notifications in both production and local mode.
When
cds.notifications.storeNotifications: trueis set, each notification is stored to the database after being sent. In production mode, the ANS-assigned notification ID is used directly. In local mode, a UUID is generated locally. Since a single notification can be sent to multiple recipients, one row per recipient is created.Changes
NotificationStorage.cds: CDS model with@PersonalDataannotations forNotifications,NotificationPropertiesandNotificationTargetParametersentitiesStoreNotificationsHandler:@Afterhandler onNotificationProviderServicethat stores notifications to DB after ANS delivery in production modeStoreNotificationsLocalHandler:@Afterhandler on ApplicationService that stores notifications to DB in local modeNotificationStorageHelper: shared helper class containing the DB persistence logic used by both handlersLocalHandler: sets the sent notifications on the event context so StoreNotificationsLocalHandler can access themNotificationServiceConfiguration: readsstoreNotificationsflag and conditionally registers the appropriate handler based on the current modeStoredNotificationsprojection andkey bookIdfield